package com.lc.activiti.process;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import com.lc.activiti.process.service.TaskGoingFlowService;
import com.lc.activiti.utils.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.EndEvent;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.engine.*;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.task.Task;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * @Title: AuditTools
 * @Description:
 * @author: 骆超
 * @date: 2021/6/15 16:48
 */
@Component
@Slf4j
public class AuditTools{
    
    
    static RepositoryService repositoryService;
    
    static HistoryService historyService;
    
    static RuntimeService runtimeService;
    
    static TaskService taskService;

    static TaskGoingFlowService taskGoingFlowService;

    @Resource
    public void setRepositoryService(RepositoryService repositoryService){
        AuditTools.repositoryService=repositoryService;
    }
    @Resource
    public void setHistoryService(HistoryService historyService){
        AuditTools.historyService=historyService;
    }
    @Resource
    public void setRuntimeService(RuntimeService runtimeService){
        AuditTools.runtimeService=runtimeService;
    }
    @Resource
    public void setTaskService(TaskService taskService){
        AuditTools.taskService=taskService;
    }
    @Resource
    public void setTaskGoingFlowService(TaskGoingFlowService taskGoingFlowService){
        AuditTools.taskGoingFlowService=taskGoingFlowService;
    }


    /**
     * 审核不通过
     * @author 骆超
     * @date 2021/6/17
     * @param task 当前任务
     */
    public static void audit(Task task, JSONObject variables,String processType) throws Exception {
        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
        // 取得当前节点的信息
        Execution execution = runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult();
        String curActivityId = execution.getActivityId();
        FlowNode curFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(curActivityId);
        //记录当前节点的原活动方向
        List<SequenceFlow> oriSequenceFlows = ObjectUtil.clone(curFlowNode.getOutgoingFlows());
        //初始化通往结束的线路
        AtomicReference<SequenceFlow> finalFlow = new AtomicReference<>();
        //找到结束的线路
        oriSequenceFlows.forEach(flow->{
            if (flow.getTargetFlowElement() instanceof EndEvent){
                finalFlow.set(flow);
            }
        });
        //清理活动方向
        curFlowNode.getOutgoingFlows().clear();
        //-1 流程撤回 0 审核不通过
        if (("-1".equals(processType)||"0".equals(processType))&&ObjectUtil.isNotNull(finalFlow.get())){
            //如果是审核不通过或者撤回，设置该节点的出线只有一条通向结束的线，以结束该任务
            curFlowNode.getOutgoingFlows().add(finalFlow.get());
        }else if("1".equals(processType)){
            //如果是审核通过，并且出线大于2条，首先排除原有通往结束点的线，剩下的线都可以走
            List<SequenceFlow> nextFlows = ObjectUtil.isNotNull(finalFlow.get())&&oriSequenceFlows.size()>1? oriSequenceFlows.stream().filter(sequenceFlow->!sequenceFlow.getId().equals(finalFlow.get().getId())).collect(Collectors.toList()):oriSequenceFlows;
            curFlowNode.getOutgoingFlows().addAll(nextFlows);
        }else{
            throw new ActivitiException("流程图绘制有误，审批失败！");
        }
        //任务审核人设置为当前登录人的id，要不然设置的角色和多人审核看不到审核记录
        if ("0".equals(processType)||"1".equals(processType)){
            taskService.setAssignee(task.getId(), JwtUtil.getUser().getId().toString());
        }else{
            taskService.setAssignee(task.getId(), "0");
        }
        // 完成任务
        taskService.complete(task.getId(),variables);
        //恢复原方向
        curFlowNode.setOutgoingFlows(oriSequenceFlows);
        taskGoingFlowService.saveGoingFlow(task,"audit");
    }

}
